package com.fanxuankai.commons.extra.spring.beans;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.lang.NonNull;

import java.util.List;
import java.util.Objects;

/**
 * Bean 延迟初始化处理器
 *
 * @author fanxuankai
 */
public abstract class AbstractLazyInitLazyInitializationBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    /**
     * Bean 类包名
     *
     * @return List
     */
    protected abstract List<String> getBeanBasePackages();

    /**
     * Bean 名称
     *
     * @return List
     */
    protected abstract List<String> getBeanNames();

    @Override
    public void postProcessBeanFactory(@NonNull ConfigurableListableBeanFactory beanFactory) throws BeansException {
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanDefinitionName);
            if (matchClassPackage(beanDefinition)
                    || getBeanNames().stream()
                    .anyMatch(s -> Objects.equals(s, beanDefinitionName))) {
                beanDefinition.setLazyInit(true);
            }
        }
    }

    private boolean matchClassPackage(BeanDefinition beanDefinition) {
        String beanClassName = beanDefinition.getBeanClassName();
        if (beanClassName == null) {
            return false;
        }
        return getBeanBasePackages().stream().anyMatch(beanClassName::startsWith);
    }
}
